package server;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Set;
import java.util.Stack;

public class MyClassLoader extends ClassLoader
{
    public MyClassLoader()
    {

    }

    public MyClassLoader(ClassLoader parent)
    {
        super(parent);
    }

    protected Class<?> findClass(String name) throws ClassNotFoundException
    {
        File file = new File(name);
        try{
            byte[] bytes = getClassBytes(file);
            //defineClass方法可以把二进制流字节组成的文件转换为一个java.lang.Class
            Class<?> c = this.defineClass(name, bytes, 0, bytes.length);
            return c;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return super.findClass(name);
    }

    private byte[] getClassBytes(File file) throws Exception
    {
        // 这里要读入.class的字节，因此要使用字节流
        FileInputStream fis = new FileInputStream(file);
        FileChannel fc = fis.getChannel();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        WritableByteChannel wbc = Channels.newChannel(baos);
        ByteBuffer by = ByteBuffer.allocate(1024);

        while (true){
            int i = fc.read(by);
            if (i == 0 || i == -1)
                break;
            by.flip();
            wbc.write(by);
            by.clear();
        }
        fis.close();
        return baos.toByteArray();
    }
//
//
//    public static Set<Class<?>> loadClasses(String rootClassPath) throws Exception {
//        Set<Class<?>> classSet = Sets.newHashSet();
//        // 设置class文件所在根路径
//        File clazzPath = new File(rootClassPath);
//
//        // 记录加载.class文件的数量
//        int clazzCount = 0;
//
//        if (clazzPath.exists() && clazzPath.isDirectory()) {
//            // 获取路径长度
//            int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;
//
//            Stack<File> stack = new Stack<>();
//            stack.push(clazzPath);
//
//            // 遍历类路径
//            while (!stack.isEmpty()) {
//                File path = stack.pop();
//                File[] classFiles = path.listFiles(new FileFilter() {
//                    public boolean accept(File pathname) {
//                        //只加载class文件
//                        return pathname.isDirectory() || pathname.getName().endsWith(".class");
//                    }
//                });
//                if (classFiles == null) {
//                    break;
//                }
//                for (File subFile : classFiles) {
//                    if (subFile.isDirectory()) {
//                        stack.push(subFile);
//                    } else {
//                        if (clazzCount++ == 0) {
//                            Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
//                            boolean accessible = method.isAccessible();
//                            try {
//                                if (!accessible) {
//                                    method.setAccessible(true);
//                                }
//                                // 设置类加载器
//                                URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
//                                // 将当前类路径加入到类加载器中
//                                method.invoke(classLoader, clazzPath.toURI().toURL());
//                            } catch (Exception e) {
//                                e.printStackTrace();
//                            } finally {
//                                method.setAccessible(accessible);
//                            }
//                        }
//                        // 文件名称
//                        String className = subFile.getAbsolutePath();
//                        className = className.substring(clazzPathLen, className.length() - 6);
//                        //将/替换成. 得到全路径类名
//                        className = className.replace(File.separatorChar, '.');
//                        // 加载Class类
//                        Class<?> aClass = Class.forName(className);
//                        classSet.add(aClass);
//                        System.out.println("读取应用程序类文件[class={" + className + "}]");
//                    }
//                }
//            }
//        }
//        return classSet;
//    }
}